package com.ae.putingotdown.block;

import com.ae.putingotdown.cap.SingleItemStackHandler;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.*;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.common.ToolType;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class PlacedIngot extends Block {
    public static IntegerProperty COUNT = IntegerProperty.create("count", 0, 8);
    public static BooleanProperty INGOT = BooleanProperty.create("ingot");
    public static EnumProperty<Direction> DIRECTION = DirectionProperty.create("direction", Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.NORTH, Direction.UP, Direction.DOWN);
    private static final VoxelShape shape1 = Block.box(0, 0, 0, 16, 2, 16);
    private static final VoxelShape shape2 = Block.box(0, 0, 0, 16, 4, 16);
    private static final VoxelShape shape3 = Block.box(0, 0, 0, 16, 6, 16);
    private static final VoxelShape shape4 = Block.box(0, 0, 0, 16, 8, 16);
    private static final VoxelShape shape5 = Block.box(0, 0, 0, 16, 10, 16);
    private static final VoxelShape shape6 = Block.box(0, 0, 0, 16, 12, 16);
    private static final VoxelShape shape7 = Block.box(0, 0, 0, 16, 14, 16);
    //如果碰撞箱是一个完整的方块，内部会出现大量阴影影响观感。
    private static final VoxelShape shape8 = Block.box(0, 0, 0, 16, 15.9d, 16);
    private static final VoxelShape shape9 = Block.box(0, 0, 0, 16, 16, 16);
    private static final VoxelShape box;

    static {
        VoxelShape bottom = Block.box(0, 0, 0, 16, 0.5, 16);
        VoxelShape wall1 = Block.box(0, 0, 0, 16, 16, 0.5);
        VoxelShape wall2 = Block.box(0, 0, 0, 0.5, 16, 16);
        VoxelShape wall3 = Block.box(0, 0, 15.5, 16, 16, 16);
        VoxelShape wall4 = Block.box(15.5, 0, 0, 16, 16, 16);
        box = VoxelShapes.or(bottom, wall1, wall2, wall3, wall4);
    }

    public PlacedIngot() {
        super(Properties
                .of(Material.METAL)
                .harvestLevel(4)
                .harvestTool(ToolType.PICKAXE)
                .sound(SoundType.METAL)
                .noOcclusion()
                .strength(3f)
        );
        registerDefaultState(getStateDefinition().any().setValue(COUNT, 1).setValue(INGOT, false).setValue(DIRECTION, Direction.NORTH));
    }

    @Override
    protected void createBlockStateDefinition(StateContainer.Builder<Block, BlockState> builder) {
        super.createBlockStateDefinition(builder);
        builder.add(COUNT).add(INGOT).add(DIRECTION);
    }

    @Override
    @Nonnull
    public ActionResultType use(@Nullable BlockState state, World world, @Nonnull BlockPos pos, @Nonnull PlayerEntity player, @Nonnull Hand hand, @Nonnull BlockRayTraceResult ray) {
        if (!world.isClientSide && !player.isShiftKeyDown() && hand == Hand.MAIN_HAND) {
            return take(world, pos, player);
        }

        return ActionResultType.PASS;
    }

    private ActionResultType take(World world, BlockPos pos, PlayerEntity player) {
        TileEntity tile = world.getBlockEntity(pos);

        //检测是否为TilPlacedIngot。
        if (!(tile instanceof TilePlacedItem)) {
            return ActionResultType.PASS;
        }

        SingleItemStackHandler handler = ((TilePlacedItem) tile).handler;

        if (handler.getStackInSlot().getCount() == handler.getMaxCount()) {
            if (take(world, pos.above(), player) == ActionResultType.SUCCESS) {
                return ActionResultType.SUCCESS;
            }
        }

        ItemStack stack = handler.extractItem(1, false);

        if (stack.isEmpty()) {
            return ActionResultType.PASS;
        }

        if (!player.inventory.add(stack)) {
            InventoryHelper.dropItemStack(world, player.position().x, player.position().y, player.position().z, stack);
        }

        return ActionResultType.SUCCESS;
    }

    @Override
    public boolean hasTileEntity(BlockState state) {
        return true;
    }

    @Nullable
    @Override
    public TileEntity createTileEntity(BlockState state, IBlockReader world) {
        return new TilePlacedItem();
    }

    @Override
    @Nonnull
    public VoxelShape getShape(BlockState state, @Nonnull IBlockReader reader, @Nonnull BlockPos pos, @Nonnull ISelectionContext context) {
        Integer count = state.getValue(COUNT);
        Boolean ingot = state.getValue(INGOT);
        switch (count) {
            case 1:
                return shape1;
            case 2:
                return ingot ? shape2 : VoxelShapes.or(box, shape2);
            case 3:
                return ingot ? shape3 : VoxelShapes.or(box, shape3);
            case 4:
                return ingot ? shape4 : VoxelShapes.or(box, shape4);
            case 5:
                return ingot ? shape5 : VoxelShapes.or(box, shape5);
            case 6:
                return ingot ? shape6 : VoxelShapes.or(box, shape6);
            case 7:
                return ingot ? shape7 : VoxelShapes.or(box, shape7);
            case 8:
                return ingot ? shape8 : shape9;
        }
        return shape1;
    }

    @Override
    public boolean canBeReplaced(@Nonnull BlockState p_196253_1_, @Nonnull BlockItemUseContext p_196253_2_) {
        return false;
    }

    @Override
    public void onRemove(BlockState state, @Nonnull World worldIn, @Nonnull BlockPos pos, BlockState newState, boolean isMoving) {
        if (!state.is(newState.getBlock())) {
            TileEntity tile = worldIn.getBlockEntity(pos);
            if (tile instanceof TilePlacedItem) {
                InventoryHelper.dropItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), ((TilePlacedItem) tile).handler.getStackInSlot());
                worldIn.updateNeighbourForOutputSignal(pos, this);
            }

            super.onRemove(state, worldIn, pos, newState, isMoving);
        }
    }

    @Override
    public boolean makesOpenTrapdoorAboveClimbable(BlockState state, IWorldReader world, BlockPos pos, BlockState trapdoorState) {
        return state.getValue(COUNT) >= 4;
    }

    /**
     * @param tile 对应方块的TilePlacedIngot
     * @return 需要展示出的锭个数
     */
    public static int getDisplayCount(TilePlacedItem tile) {
        int maxCount = tile.handler.getMaxCount();
        int count = tile.handler.getStackInSlot().getCount();

        return (int) Math.ceil(64d * count / maxCount);
    }
}
